//
//  PurchaseViewController.swift
//  SitPosition
//
//  Created by apple on 2019/2/7.
//  Copyright © 2019 apple. All rights reserved.
//

import Foundation
import UIKit
import Cartography
import Toast_Swift


/**
 * 支付类型视图
 */
class PurchaseTypeView : UIView {
    
    // 数据模型
    struct Model {
        let image: UIImage?
        let title: String
        let subtitle: String
    }
    
    // MARK: - Properties
    public var onSelectionChanged: (() -> Void)?
    public var isSelected: Bool {
        get {
            return checkboxBtn.isSelected
        }
        set {
            checkboxBtn.isSelected = newValue
        }
    }
    public var model: Model? = nil {
        didSet {
            iconIV.image = model?.image
            titleLabel.text = model?.title
            subtitleLabel.text = model?.subtitle
        }
    }
    
    // Icon
    private lazy var iconIV: UIImageView = {
        let iv = UIImageView()
        iv.contentMode = UIView.ContentMode.scaleAspectFit
        return iv
    }()
    
    // 标题
    private lazy var titleLabel: UILabel = {
        let label = UILabel()
        label.textColor = Theme.Color.primaryDark2TextColor
        label.font = Theme.Font.regularFont(ofSize: 15)
        label.lineBreakMode = NSLineBreakMode.byTruncatingTail
        label.textAlignment = NSTextAlignment.left
        label.numberOfLines = 1
        return label
    }()
    
    // 子标题
    private lazy var subtitleLabel: UILabel = {
        let label = UILabel()
        label.textColor = Theme.Color.primaryDarkGrayTextColor
        label.font = Theme.Font.regularFont(ofSize: 12)
        label.lineBreakMode = NSLineBreakMode.byTruncatingTail
        label.textAlignment = NSTextAlignment.left
        label.numberOfLines = 1
        return label
    }()
    
    // 选择框
    private lazy var checkboxBtn: UIButton = {
        let btn = UIButton(type: UIButton.ButtonType.custom)
        btn.setImage(UIImage(named: "choice_normal"), for: UIControl.State.normal)
        btn.setImage(UIImage(named: "choice_selected"), for: UIControl.State.selected)
        btn.addTarget(self, action: #selector(_handleToggleSelection), for: UIControl.Event.touchUpInside)
        return btn
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        _commonInit()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        _commonInit()
    }
    
    private func _commonInit() {
        // Self
        backgroundColor = UIColor.white
        layer.cornerRadius = 2
        layer.shadowRadius = 8
        layer.shadowOpacity = 1
        layer.shadowOffset = CGSize(width: 0, height: 3)
        layer.shadowColor = UIColor(hexString: "#BBC5FF", alpha: 0.32).cgColor
        
        // Gesture
        let tapGR = UITapGestureRecognizer(target: self, action: #selector(_handleToggleSelection))
        tapGR.numberOfTouchesRequired = 1
        tapGR.numberOfTapsRequired = 1
        addGestureRecognizer(tapGR)
        
        // 子视图
        addSubviews([
            iconIV,
            titleLabel,
            subtitleLabel,
            checkboxBtn
        ])
        _setupContraints()
    }
    
    // 设置视图约束
    func _setupContraints() {
        
        // iconIV
        constrain(iconIV, self) { v, parent in
            v.left == parent.left + 11
            v.centerY == parent.centerY
            v.width == 40
            v.height == 40
        }
        
        // titleLabel
        constrain(titleLabel, iconIV, self) { v, sibling, parent in
            v.top == sibling.top
            v.left == sibling.right + 8
            v.right == parent.right - 38
            v.height == sibling.height / 2
        }
        
        // subtitleLabel
        constrain(subtitleLabel, iconIV, self) { v, sibling, parent in
            v.left == sibling.right + 8
            v.right == parent.right - 38
            v.bottom == sibling.bottom
            v.height == sibling.height / 2
        }
        
        // checkboxBtn
        constrain(checkboxBtn, self) { v, parent in
            v.right == parent.right - 15
            v.centerY == parent.centerY
            v.width == 15
            v.height == 15
        }
    }
    
    @objc private func _handleToggleSelection() {
        checkboxBtn.isSelected = true
        onSelectionChanged?()
    }
}


/**
 * 支付购买页面
 */
class PurchaseViewController : GKNavigationBarViewController {
    
    // 标题
    lazy var titleLabel: UILabel = {
        let label = UILabel()
        label.textColor = Theme.Color.primaryDarkTextColor
        label.font = Theme.Font.boldFont(ofSize: 26)
        label.numberOfLines = 1
        label.lineBreakMode = .byTruncatingTail
        label.text = Strings.purchaseTitle
        return label
    }()
    
    // 价格
    // TODO: 从服务器拉取
    var price: Double = 168 {
        didSet {
            _updatePriceLabel()
        }
    }
    lazy var priceLabel: UILabel = {
        let label = UILabel()
        label.textColor = Theme.Color.priceColor
        label.font = Theme.Font.boldFont(ofSize: 21)
        label.numberOfLines = 1
        label.lineBreakMode = .byTruncatingTail
        return label
    }()
    
    // 商品名称
    lazy var productLabel: UILabel = {
        let label = UILabel()
        label.textColor = Theme.Color.primaryDarkTextColor
        label.font = Theme.Font.boldFont(ofSize: 21)
        label.numberOfLines = 1
        label.lineBreakMode = .byTruncatingTail
        label.text = Strings.purchaseProductTitle
        return label
    }()
    
    // 支付方式
    private var purchaseType: PurchaseType = .weichat {
        didSet {
            _udpatePurchaseTypeViews()
        }
    }

    // 微信支付
    lazy var weichatView: PurchaseTypeView = {
        let view = PurchaseTypeView(frame: CGRect.zero)
        view.model = PurchaseTypeView.Model(image: UIImage(named: "wechat"),
                                            title: Strings.purchaseWechat,
                                            subtitle: Strings.purchaseWechatDetails)
        view.isSelected = true
        view.onSelectionChanged = { [weak self] in
            self?.purchaseType = .weichat
        }
        return view
    }()
    
    // 支付宝支付
    lazy var alipayView: PurchaseTypeView = {
        let view = PurchaseTypeView(frame: CGRect.zero)
        view.model = PurchaseTypeView.Model(image: UIImage(named: "alipay"),
                                            title: Strings.purchaseAlipay,
                                            subtitle: Strings.purchaseAlipayDetails)
        view.isSelected = true
        view.onSelectionChanged = { [weak self] in
            self?.purchaseType = .alipay
        }
        return view
    }()
    
    // 立即购买使用
    lazy var purchaseBtn: UIButton = {
        let btn = UIButton(type: UIButton.ButtonType.custom)
        btn.backgroundColor = Theme.Color.priceColor
        btn.setTitle(Strings.purchaseNow, for: UIControl.State.normal)
        btn.titleLabel?.font = Theme.Font.boldFont(ofSize: 16)
        btn.setTitleColor(UIColor.white, for: UIControl.State.normal)
        btn.addTarget(self, action: #selector(_handlePurchasNow), for: UIControl.Event.touchUpInside)
        return btn
    }()
    
    // MARK: - Object lifecycle
    let order: UserPendingOrder
    
    required init(_ order: UserPendingOrder) {
        self.order = order
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("Not implemented yet")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.white
        
        // 导航栏
        gk_navBackgroundColor = UIColor.clear
        gk_navLeftBarButtonItem = UIBarButtonItem(imageName: "ic_nav_back_black", target: self, action: #selector(_backButtonTapped))
        
        // 背景图
        let bkImage: UIImage? = UIImage(named: "hm")
        let bkIV: UIImageView = UIImageView(image: bkImage)
        bkIV.backgroundColor = UIColor.clear
        bkIV.contentMode = UIView.ContentMode.scaleAspectFit
        view.addSubview(bkIV)
        constrain(bkIV, view) { (v, parent) in
            v.left == parent.left
            v.right == parent.right + 160
            v.top == parent.top - 120
            v.bottom == parent.bottom
        }
        
        // 子视图
        view.addSubviews([
            titleLabel,
            priceLabel,
            productLabel,
            weichatView,
            alipayView,
            purchaseBtn
        ])
        _setupContraints()
        
        // 更新价格
        _fetchProductPrice()
        _udpatePurchaseTypeViews()
        
        // 设置微信、支付宝代理
        if let appDelegate: AppDelegate = UIApplication.shared.delegate as? AppDelegate {
            appDelegate.wxApiDelegate = self
            appDelegate.aliPayDelegate = self
        }
        
    }
    
}


// MARK: - Private Methods

extension PurchaseViewController {
    
    // 设置视图约束
    func _setupContraints() {
        
        // titleLabel
        constrain(titleLabel, gk_navigationBar, view) { v, sibling, parent in
            v.top == sibling.bottom + 19
            v.left == parent.left + 16
            v.right == parent.right - 16
            v.height == 25
        }
        
        // priceLabel
        constrain(priceLabel, titleLabel, view) { v, sibling, parent in
            v.top == sibling.bottom + 46
            v.left == sibling.left
            v.right == sibling.right
            v.height == 32
        }
        
        // productLabel
        constrain(productLabel, priceLabel, view) { v, sibling, parent in
            v.top == sibling.bottom + 11
            v.left == sibling.left
            v.right == sibling.right
            v.height == 20
        }
        
        // weichatView
        constrain(weichatView, productLabel, view) { v, sibling, parent in
            v.top == sibling.bottom + 72
            v.left == sibling.left
            v.right == sibling.right
            v.height == 70
        }
        
        // alipayView
        constrain(alipayView, weichatView, view) { v, sibling, parent in
            v.top == sibling.bottom + 20
            v.left == sibling.left
            v.right == sibling.right
            v.height == sibling.height
        }
        
        // purchaseBtn
        constrain(purchaseBtn, view) { v, parent in
            v.bottom == parent.bottom - 15
            v.left == parent.left + 15
            v.right == parent.right - 15
            v.height == 50
        }
    }
    
    // 拉取价格信息
    func _fetchProductPrice() {
        view.makeToastActivity(ToastPosition.center)
        NetworkClient.instance.productPrice(success: { [weak self] (data) in
            self?.view.hideToastActivity()
            
            guard let data_ = data else {
                self?.view.makeToast(SPError.unexpectedServerResponse.localizedDescription)
                return
            }
            do {
                let decoder: JSONDecoder = JSONDecoder()
                let priceModel = try decoder.decode(ProductPrice.self, from: data_)
                self?.price = priceModel.data.productFee
            } catch {
                self?.view.makeToast(error.localizedDescription)
            }
        }, failure: { [weak self] (error) in
            self?.view.makeToast(error?.localizedDescription ?? Strings.errUnknown)
        })
    }
    
    // 更新价格标签
    func _updatePriceLabel() {
        let string = String("￥\(price)")
        let attribString = NSMutableAttributedString(string: string)
        attribString.addAttributes([NSAttributedString.Key.font : Theme.Font.boldFont(ofSize: 21),
                                    NSAttributedString.Key.foregroundColor : Theme.Color.priceColor],
                                   range: NSRange(location: 0, length: 1))
        attribString.addAttributes([NSAttributedString.Key.font : Theme.Font.boldFont(ofSize: 41),
                                    NSAttributedString.Key.foregroundColor : Theme.Color.priceColor],
                                   range: NSRange(location: 1, length: string.count - 1))
        priceLabel.attributedText = attribString
    }
    
    // 更新支付方式视图
    func _udpatePurchaseTypeViews() {
        switch purchaseType {
        case .weichat:
            weichatView.isSelected = true
            alipayView.isSelected = false
        case .alipay:
            weichatView.isSelected = false
            alipayView.isSelected = true
        }
    }
    
    // 返回按钮点击事件
    private func _popup() {
        if presentingViewController != nil {
            dismiss(animated: true, completion: nil)
        } else {
            navigationController?.popViewController(animated: true)
        }
    }
    
    @objc func _backButtonTapped() { /* 关闭的前提条件是支付成功 */ }
    
    // 立即购买
    @objc func _handlePurchasNow() {
        let failure: ErrorCallback = { [weak self] (error) in
            self?.view.hideToastActivity()
            self?.view.makeToast(error?.localizedDescription ?? Strings.errUnknown)
        }
        view.makeToastActivity(ToastPosition.center)
        let purchaseType_: PurchaseType = purchaseType
        NetworkClient.instance.payOrder(id: order.id, payMethod: purchaseType, success: { [weak self] (data) in
            guard let data_ = data else {
                failure(SPError.unexpectedServerResponse)
                return
            }
            do {
                let decoder: JSONDecoder = JSONDecoder()
                let payParams: UserOrderPayParams
                switch purchaseType_ {
                case .alipay:
                    payParams = try decoder.decode(UserOrderAliPayParams.self, from: data_)
                case .weichat:
                    payParams = try decoder.decode(UserOrderWechatPayParams.self, from: data_)
                }
                self?._pay(payParams)
            } catch {
                failure(error)
            }
        }, failure: failure)
    }
    
    private func _pay(_ payParams: UserOrderPayParams) {
        let failure: ErrorCallback = { [weak self] (error) in
            self?.view.hideToastActivity()
            self?.view.makeToast(error?.localizedDescription ?? Strings.errUnknown)
        }
        
        switch purchaseType {
        case .alipay:
            guard let aliPayParams = payParams as? UserOrderAliPayParams else {
                failure(SPError.unexpectedServerResponse)
                return
            }
            
            // 发起支付请求...
            AlipaySDK.defaultService()?.payOrder(aliPayParams.payUrl.url, fromScheme: "sitposition", callback: { (resultDict) in
                dbgPrint("\(resultDict ?? [:])")
            })
        case .weichat:
            guard let wechatPayParams = payParams as? UserOrderWechatPayParams else {
                failure(SPError.unexpectedServerResponse)
                return
            }
            let appPay = wechatPayParams.appPay
            
            // 发起支付请求...
            let req: PayReq = PayReq()
            req.partnerId = appPay.partnerid
            req.prepayId  = appPay.prepayid
            req.package   = appPay.package
            req.nonceStr  = appPay.noncestr
            req.timeStamp = UInt32(appPay.timestamp ?? 0)
            req.sign      = appPay.sign
            WXApi.send(req)
        }
    }
    
}


// MARK: - WXApiDelegate / AliPayDelegate

extension PurchaseViewController : WXApiDelegate, AliPayDelegate {
    
    /*! @brief 发送一个sendReq后，收到微信的回应
     *
     * 收到一个来自微信的处理结果。调用一次sendReq后会收到onResp。
     * 可能收到的处理结果有SendMessageToWXResp、SendAuthResp等。
     * @param resp具体的回应内容，是自动释放的
     */
    func onResp(_ resp: BaseResp) {
        switch resp {
        case is PayResp:
            let payResp: PayResp = resp as! PayResp
            switch payResp.errCode {
            case 0: _payRequestSuccess()
            case -2: _payRequestCancelled()
            default: _payRequestFailure(error: payResp.errStr)
            }
        default: break
        }
    }
    
    // 支付宝支付结果响应回调
    func alipayResponse(_ resultDict: [AnyHashable : Any]?) {
        guard let resultDict_ = resultDict,
            let resultStatus = resultDict_["resultStatus"] as? String else {
                return
        }
        let status: Int = (resultStatus as NSString).integerValue
        let message: String? = resultDict_["memo"] as? String
        switch status {
        case 9000:  // 订单支付成功
            _payRequestSuccess()
        case 6001:  // 用户中途取消
            _payRequestCancelled()
        default:
            _payRequestFailure(error: message ?? "")
        }
    }
    
    private func _payRequestCancelled() {
        DispatchQueue.main.async { [weak self] in
            self?.view.hideToastActivity()
            self?.view.makeToast(Strings.purchaseCanncelled)
        }
    }
    
    private func _payRequestSuccess() {
        DispatchQueue.main.async { [weak self] in
            self?.view.hideToastActivity()
            self?.view.makeToast(Strings.purchaseSuccess)
            
            // 关闭当前支付页面
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2, execute: {
                self?._popup()
            })
        }
    }
    
    private func _payRequestFailure(error: String) {
        DispatchQueue.main.async { [weak self] in
            self?.view.hideToastActivity()
            let errMessage: String
            if error.isEmpty {
                errMessage = Strings.errUnknown
            } else {
                errMessage = error
            }
            let message = (Strings.purchaseFailure as NSString)
                .replacingOccurrences(of: "$ERROR", with: errMessage)
            self?.view.makeToast(message)
        }
    }
}


